home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / borcmpad / mpfind.c < prev    next >
C/C++ Source or Header  |  1991-07-23  |  8KB  |  273 lines

  1. /***************************************************************************
  2.  *                                       *
  3.  *  MODULE    : MpFind.c                               *
  4.  *                                       *
  5.  *  PURPOSE    : Code to do text searches in MultiPad.            *
  6.  *                                       *
  7.  *  FUNCTIONS    : RealSlowCompare () - Compares subject string with target *
  8.  *                       string.                   *
  9.  *                                       *
  10.  *          FindText ()         - Looks for the search string in the  *
  11.  *                       active window.               *
  12.  *                                       *
  13.  *          FindPrev ()         - Find previous occurence of search   *
  14.  *                       string.                   *
  15.  *                                       *
  16.  *          FindNext ()         - Find next occurence of search string*
  17.  *                                       *
  18.  *          FindDlgProc ()     - Dialog function for Search/Find.    *
  19.  *                                       *
  20.  *          Find ()         - Invokes FindDlgProc ()           *
  21.  *                                       *
  22.  ***************************************************************************/
  23. #include "multipad.h"
  24.  
  25. #undef HIWORD
  26. #undef LOWORD
  27.  
  28. #define HIWORD(l) (((WORD*)&(l))[1])
  29. #define LOWORD(l) (((WORD*)&(l))[0])
  30.  
  31. BOOL fCase       = FALSE;    /* Turn case sensitivity off */
  32. char szSearch[160] = "";       /* Initialize search string  */
  33.  
  34. /****************************************************************************
  35.  *                                        *
  36.  *  FUNCTION   : RealSlowCompare ()                        *
  37.  *                                        *
  38.  *  PURPOSE    : Compares subject string with the target string. This fn/   *
  39.  *         is called repeatedly so that all substrings are compared,  *
  40.  *         which makes it O(n ** 2), hence it's name.                 *
  41.  *                                        *
  42.  *  RETURNS    : TRUE  - If pSubject is identical to pTarget.            *
  43.  *         FALSE - otherwise.                        *
  44.  *                                        *
  45.  ****************************************************************************/
  46.  
  47. BOOL NEAR PASCAL RealSlowCompare (pSubject, pTarget )
  48. register PSTR pSubject;
  49. register PSTR pTarget;
  50. {
  51.     if (fCase){
  52.     while (*pTarget)
  53.         if (*pTarget++ != *pSubject++)
  54.         return FALSE;
  55.     }
  56.     else{
  57.     /* If case-insensitive, convert both subject and target to lowercase
  58.      * before comparing.
  59.      */
  60.     AnsiLower ((LPSTR)pTarget);
  61.     while (*pTarget)
  62.         if (*pTarget++ != (char)(DWORD)AnsiLower ((LPSTR)(DWORD)(BYTE)*pSubject++))
  63.         return FALSE;
  64.     }
  65.     return TRUE;
  66. }
  67.  
  68. /****************************************************************************
  69.  *                                        *
  70.  *  FUNCTION   : FindText ()                            *
  71.  *                                        *
  72.  *  PURPOSE    : Finds the search string in the active window according to  *
  73.  *         search direction (dch) specified ( -1 for reverse and 1 for*
  74.  *         forward searches).                        *
  75.  *                                        *
  76.  ****************************************************************************/
  77. VOID NEAR PASCAL FindText( dch )
  78. register int dch;
  79.  
  80. {
  81.     register PSTR pText;
  82.     HANDLE      hT;
  83.     LONG      l;
  84.     WORD      cch;
  85.     int       i;
  86.  
  87.     if (!*szSearch)
  88.     return;
  89.  
  90.     /* Find the current selection range */
  91.     l = SendMessage(hwndActiveEdit, EM_GETSEL, 0, 0L);
  92.  
  93.     /* Get the handle to the text buffer and lock it */
  94.     hT      = (HANDLE)SendMessage (hwndActiveEdit, EM_GETHANDLE, 0, 0L);
  95.     pText = LocalLock(hT);
  96.  
  97.     /* Get the length of the text */
  98.     cch = (WORD)SendMessage (hwndActiveEdit, WM_GETTEXTLENGTH, 0, 0L);
  99.  
  100.     /* Start with the next char. in selected range ... */
  101.     pText += LOWORD (l) + dch;
  102.  
  103.     /* Compute how many characters are before/after the current selection*/
  104.     if (dch < 0)
  105.     i = LOWORD (l);
  106.     else
  107.     i = cch - LOWORD (l) + 1 - lstrlen (szSearch);
  108.  
  109.     /* While there are uncompared substrings... */
  110.     while ( i > 0){
  111.     LOWORD(l)+=dch;
  112.  
  113.     /* Does this substring match? */
  114.     if (RealSlowCompare(pText,szSearch)){
  115.  
  116.         /* Yes, unlock the buffer.*/
  117.         LocalUnlock(hT);
  118.  
  119.         /* Select the located string */
  120.         HIWORD(l) = LOWORD(l) + lstrlen (szSearch);
  121.         SendMessage (hwndActiveEdit, EM_SETSEL, 0, l);
  122.         return;
  123.     }
  124.     i--;
  125.  
  126.     /* increment/decrement start position by 1 */
  127.     pText += dch;
  128.     }
  129.  
  130.     /* Not found... unlock buffer. */
  131.     LocalUnlock (hT);
  132.  
  133.     /* Give a message */
  134.     MPError (hwndFrame, MB_OK | MB_ICONEXCLAMATION, IDS_CANTFIND, (LPSTR)szSearch);
  135.  
  136.     return;
  137. }
  138.  
  139. /****************************************************************************
  140.  *                                        *
  141.  *  FUNCTION   : FindPrev ()                            *
  142.  *                                        *
  143.  *  PURPOSE    : Finds the previous occurence of the search string. Calls   *
  144.  *         FindText () with a negative search direction.            *
  145.  *                                        *
  146.  ****************************************************************************/
  147. VOID FAR PASCAL FindPrev(void)
  148. {
  149.     FindText(-1);
  150. }
  151.  
  152. /****************************************************************************
  153.  *                                        *
  154.  *  FUNCTION   : FindNext ()                            *
  155.  *                                        *
  156.  *  PURPOSE    : Finds the next occurence of search string. Calls        *
  157.  *         FindText () with a positive search direction.            *
  158.  *                                        *
  159.  ****************************************************************************/
  160. VOID FAR PASCAL FindNext(void)
  161. {
  162.     FindText(1);
  163. }
  164.  
  165. /****************************************************************************
  166.  *                                        *
  167.  *  FUNCTION   : FindDlgProc(hwnd, message, wParam, lParam)            *
  168.  *                                        *
  169.  *  PURPOSE    : Dialog function for the Search/Find command. Prompts user  *
  170.  *         for target string, case flag and search direction.        *
  171.  *                                        *
  172.  ****************************************************************************/
  173. BOOL FAR PASCAL FindDlgProc(hwnd, msg, wParam, lParam)
  174. HWND hwnd;
  175. WORD msg;
  176. WORD wParam;
  177. LONG lParam;
  178. {
  179.     switch (msg){
  180.     case WM_INITDIALOG:{
  181.  
  182.         /* Check/uncheck case button */
  183.         CheckDlgButton (hwnd, IDD_CASE, fCase);
  184.  
  185.         /* Set default search string to most recently searched string */
  186.         SetDlgItemText (hwnd, IDD_SEARCH, szSearch);
  187.  
  188.         /* Allow search only if target is nonempty */
  189.         if (!lstrlen (szSearch)){
  190.         EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
  191.         EnableWindow (GetDlgItem (hwnd, IDD_PREV), FALSE);
  192.         }
  193.         break;
  194.     }
  195.  
  196.     case WM_COMMAND:{
  197.  
  198.         /* Search forward by default (see IDOK below) */
  199.         int i = 1;
  200.  
  201.         switch (wParam){
  202.         /* if the search target becomes non-empty, enable searching */
  203.         case IDD_SEARCH:
  204.             if (HIWORD(lParam) == EN_CHANGE){
  205.             if (!(WORD) SendDlgItemMessage (hwnd,
  206.                             IDD_SEARCH,
  207.                             WM_GETTEXTLENGTH,
  208.                             0,
  209.                             0L))
  210.                 i = FALSE;
  211.             else
  212.                 i = TRUE;
  213.             EnableWindow (GetDlgItem (hwnd, IDOK), i);
  214.             EnableWindow (GetDlgItem (hwnd, IDD_PREV), i);
  215.             }
  216.             break;
  217.  
  218.         case IDD_CASE:
  219.             /* Toggle state of case button */
  220.             CheckDlgButton (hwnd,
  221.                     IDD_CASE,
  222.                     !IsDlgButtonChecked (hwnd, IDD_CASE));
  223.             break;
  224.  
  225.         case IDD_PREV:
  226.             /* Set direction to backwards */
  227.             i=-1;
  228.             /*** FALL THRU ***/
  229.  
  230.         case IDOK:
  231.             /* Save case selection */
  232.             fCase = IsDlgButtonChecked( hwnd, IDD_CASE);
  233.  
  234.             /* Get search string */
  235.             GetDlgItemText (hwnd, IDD_SEARCH, szSearch, sizeof (szSearch));
  236.  
  237.             /* Find the text */
  238.             FindText (i);
  239.             /*** FALL THRU ***/
  240.  
  241.         /* End the dialog */
  242.         case IDCANCEL:
  243.             EndDialog (hwnd, 0);
  244.             break;
  245.  
  246.         default:
  247.             return FALSE;
  248.         }
  249.         break;
  250.     }
  251.     default:
  252.         return FALSE;
  253.     }
  254.     return TRUE;
  255. }
  256.  
  257. /****************************************************************************
  258.  *                                        *
  259.  *  FUNCTION   : Find()                             *
  260.  *                                        *
  261.  *  PURPOSE    : Invokes the Search/Find dialog.                *
  262.  *                                        *
  263.  ****************************************************************************/
  264.  
  265. VOID FAR PASCAL Find()
  266. {
  267.     FARPROC lpfn;
  268.  
  269.     lpfn = MakeProcInstance (FindDlgProc, hInst);
  270.     DialogBox (hInst, IDD_FIND, hwndFrame, lpfn);
  271.     FreeProcInstance (lpfn);
  272. }
  273.